﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Collections;

namespace Kevin.SLUserControlLibrary
{
    public enum ScollMode
    {
        Line,
        Panel
    }

    public class NoticePanel : ContentControl
    {
        #region DependencyProperty
        public static readonly DependencyProperty ItemSourceProperty = DependencyProperty.Register("ItemSource", typeof(IEnumerable), typeof(NoticePanel),
            new PropertyMetadata(null, (new PropertyChangedCallback(OnItemSourcePropertyChanged))));

        public static readonly DependencyProperty ScollModeProperty = DependencyProperty.Register("ScollMode", typeof(ScollMode), typeof(NoticePanel),
            new PropertyMetadata(ScollMode.Line, (new PropertyChangedCallback(OnItemSourcePropertyChanged))));

        #endregion

        private Queue<TextBlock> queue = new Queue<TextBlock>();
        private StackPanel ElementNoticePanel;
        private TextBlock topTextBlock;
        private Storyboard storyboard;
        private DoubleAnimation doubleAnimation;
        private double noticePanelHeight;
        private const double SPEED_RATE = 1;

        public IEnumerable ItemSource
        {
            get { return (IEnumerable)this.GetValue(NoticePanel.ItemSourceProperty); }
            set { this.SetValue(NoticePanel.ItemSourceProperty, value); }
        }

        public ScollMode ScollMode
        {
            get { return (ScollMode)this.GetValue(NoticePanel.ScollModeProperty); }
            set { this.SetValue(NoticePanel.ScollModeProperty, value); }
        }

        public NoticePanel()
        {
            this.DefaultStyleKey = typeof(NoticePanel);
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this.ElementNoticePanel = this.GetTemplateChild("ElementNoticePanel") as StackPanel;
            //this.ElementNoticePanel.Loaded += new RoutedEventHandler(ElementNoticePanel_Loaded);
            this.ElementNoticePanel.SizeChanged += new SizeChangedEventHandler(ElementNoticePanel_SizeChanged);
            this.SetNoticePanel();
        }

        void ElementNoticePanel_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            this.noticePanelHeight = 0;
            foreach (var item in this.queue)
            {
                this.noticePanelHeight += (item as TextBlock).ActualHeight;
            }
            this.SetScoll();
        }

        //void ElementNoticePanel_Loaded(object sender, RoutedEventArgs e)
        //{
        //    this.noticePanelHeight = 0;
        //    foreach (var item in this.queue)
        //    {
        //        this.noticePanelHeight += (item as TextBlock).ActualHeight;
        //    }
        //    this.SetScoll();
        //}

        protected override void OnMouseEnter(MouseEventArgs e)
        {
            base.OnMouseEnter(e);
            if (this.storyboard.GetCurrentState() == ClockState.Active)
            {
                this.storyboard.Pause();
            }
        }

        protected override void OnMouseLeave(MouseEventArgs e)
        {
            base.OnMouseLeave(e);
            if (this.storyboard.GetCurrentState() == ClockState.Active)
            {
                this.storyboard.Resume();
            }
        }

        private void SetNoticePanel()
        {
            if (this.ElementNoticePanel != null)
            {
                this.ElementNoticePanel.Children.Clear();

                if (this.ItemSource != null)
                {
                    foreach (var item in this.ItemSource)
                    {
                        TextBlock tb = new TextBlock();
                        tb.Text = item.ToString();
                        tb.TextWrapping = TextWrapping.Wrap;
                        tb.Width = this.Width;
                        queue.Enqueue(tb);
                        this.ElementNoticePanel.Children.Add(tb);

                        Rect rect = new Rect();
                        tb.Arrange(rect);
                    }
                }
            }
        }

        private void SetScoll()
        {
            if (this.ScollMode == SLUserControlLibrary.ScollMode.Line)
            {
                this.InitStoryboardByLine();
                this.SetScollByLine();
            }
            else
            {
                this.InitStoryboardByPanel();
                this.SetScollByPanel();
            }
        }

        private void SetScollByLine()
        {
            if (this.queue.Count > 0)
            {
                this.storyboard.Stop();
                this.topTextBlock = this.queue.Dequeue();

                if (noticePanelHeight > this.Height)
                {
                    Storyboard.SetTarget(doubleAnimation, this.topTextBlock);
                    this.storyboard.Begin();
                }
            }
        }

        private void SetScollByPanel()
        {
            if (noticePanelHeight > this.Height)
            {
                TranslateTransform tts = new TranslateTransform();
                tts.Y = this.Height;
                this.ElementNoticePanel.RenderTransform = tts;

                this.storyboard.Stop();
                Storyboard.SetTarget(doubleAnimation, tts);
                this.storyboard.Begin();
            }
        }

        public void InitStoryboardByLine()
        {
            this.storyboard = new Storyboard();
            doubleAnimation = new DoubleAnimation();
            doubleAnimation.From = 1.0;
            doubleAnimation.To = 0.1;
            doubleAnimation.Duration = new System.Windows.Duration(TimeSpan.FromSeconds(1));
            doubleAnimation.BeginTime = TimeSpan.FromSeconds(1);

            Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(TextBlock.Opacity)"));
            this.storyboard.Children.Add(doubleAnimation);

            this.storyboard.Completed += new EventHandler(storyboard_Completed);
        }

        private void storyboard_Completed(object sender, EventArgs e)
        {
            if (this.topTextBlock != null)
            {
                this.ElementNoticePanel.Children.Remove(this.topTextBlock);
                this.queue.Enqueue(this.topTextBlock);
                this.ElementNoticePanel.Children.Add(this.topTextBlock);
            }

            this.topTextBlock = this.queue.Dequeue();
            this.storyboard.Stop();
            Storyboard.SetTarget(doubleAnimation, this.topTextBlock);
            this.storyboard.Begin();
        }

        public void InitStoryboardByPanel()
        {
            this.storyboard = new Storyboard();
            doubleAnimation = new DoubleAnimation();
            doubleAnimation.From = this.Height;
            doubleAnimation.To = -this.noticePanelHeight;
            doubleAnimation.Duration = new System.Windows.Duration(TimeSpan.FromSeconds(this.queue.Count * SPEED_RATE));
            doubleAnimation.BeginTime = TimeSpan.FromSeconds(0);
            doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

            Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(TranslateTransform.Y)"));
            this.storyboard.Children.Add(doubleAnimation);

        }

        private static void OnItemSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((NoticePanel)d).SetNoticePanel();
        }

        private static void OnScollModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((NoticePanel)d).SetScoll();
        }
    }
}
